using System;
using System.Runtime.Serialization;
using CI.Interfaces;

namespace CI.Organism
{
    /// <summary>The organisms location</summary>
    [DataContract]
    public class Location : ILocation
    {

        #region ILocation Members

        /// <summary>X Axis position</summary>
        [DataMember]
        public float XAxis
        {
            get
            {
                return _xAxis;
            }
            set
            {
                _xAxis = value;
            }
        }
        private float _xAxis;

        /// <summary>Y Axis position</summary>
        [DataMember]
        public float YAxis
        {
            get
            {
                return _yAxis;
            }
            set
            {
                _yAxis = value;
            }
        }
        private float _yAxis;

        /// <summary>Z Axis position</summary>
        [DataMember]
        public float ZAxis
        {
            get
            {
                return _zAxis;
            }
            set
            {
                _zAxis = value;
            }
        }
        private float _zAxis;

        /// <summary>Max X radius used for basic collision detection</summary>
        [DataMember]
        public float XRadius
        {
            get
            {
                return _xRadius;
            }
            set
            {
                _xRadius = value;
            }
        }
        private float _xRadius;

        /// <summary>Max Y radius used for basic collision detection</summary>
        [DataMember]
        public float YRadius
        {
            get
            {
                return _yRadius;
            }
            set
            {
                _yRadius = value;
            }
        }
        private float _yRadius;

        /// <summary>Max Z radius used for basic collision detection</summary>
        [DataMember]
        public float ZRadius
        {
            get
            {
                return _zRadius;
            }
            set
            {
                _zRadius = value;
            }
        }
        private float _zRadius;

        #endregion

        /// <summary>
        /// Create the location with it set to just above the ground to fall
        /// </summary>
        public Location() : this(0, 1, 0) { }

        /// <summary>
        /// Create new location based on passed in one
        /// </summary>
        /// <param name="location"></param>
        public Location(ILocation location) : this(location.XAxis, location.YAxis, location.ZAxis, location.XRadius, location.YRadius, location.ZRadius) { }

        /// <summary>
        /// Create the location based on values passed to it with a radius of 1
        /// </summary>
        public Location(float x, float y, float z) : this(x, y, z, 1, 1, 1) { }

        /// <summary>
        /// Create the location based on values passed to it
        /// </summary>
        /// <param name="x">x location</param>
        /// <param name="y">y location</param>
        /// <param name="z">z location</param>
        /// <param name="xRadius">x radius</param>
        /// <param name="yRadius">y radius</param>
        /// <param name="zRadius">z radius</param>
        public Location(float x, float y, float z, float xRadius, float yRadius, float zRadius)
        {
            // location
            XAxis = x;
            YAxis = y;
            ZAxis = z;

            // radius
            XRadius = xRadius;
            YRadius = yRadius;
            ZRadius = zRadius;
        }

        /// <summary>
        /// Compare and see if the axis and raidus values are equal
        /// </summary>
        /// <returns></returns>
        public override bool Equals(Object obj)
        {

            // compare the axis values
            if (XAxis != ((Location)obj).XAxis)
                return false;
            if (YAxis != ((Location)obj).YAxis)
                return false;
            if (ZAxis != ((Location)obj).ZAxis)
                return false;

            // compare the radius
            if (XRadius != ((Location)obj).XRadius)
                return false;
            if (YRadius != ((Location)obj).YRadius)
                return false;
            if (ZRadius != ((Location)obj).ZRadius)
                return false;

            // else if all good return true
            return true;
        }

        /// <summary>
        /// Get a object hash code
        /// </summary>
        /// <returns></returns>
        public override int GetHashCode()
        {
            return base.GetHashCode();
        }

        /// <summary>Compare this objects location with another just on the x, y , z axis, not the radius etc</summary>
        /// <param name="location">Comparing object</param>
        /// <returns>are the the same location?</returns>
        public bool CompareAxis(ILocation location, int compareDecimalPlaces)
        {
            // compare the values
            if (Math.Round(XAxis, compareDecimalPlaces) != Math.Round(location.XAxis, compareDecimalPlaces))
                return false;
            if (Math.Round(YAxis, compareDecimalPlaces) != Math.Round(location.YAxis, compareDecimalPlaces))
                return false;
            if (Math.Round(ZAxis, compareDecimalPlaces) != Math.Round(location.ZAxis, compareDecimalPlaces))
                return false;

            // else if all good return true
            return true;
        }
    }
}